import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;

public class BigDecimalDemo {
    public static void main(String[] args) {
        System.out.println("BigDecimal 可表示任意精度的浮点数，它用 BigInteger 表示数值，用 scale 表示浮点偏移，比如：\n" +
                "1.2345 由 12345 和 scale=4 表示\n" +
                "12345 由 12345 和 scale=0 表示\n" +
                "12345000  可由 12345000 和 scale=0 表示，也可由 12345 和 scale=-3 表示");

        System.out.println("\n常量：");
        System.out.println("BigDecimal.ZERO = " + BigDecimal.ZERO);
        System.out.println("BigDecimal.ONE = " + BigDecimal.ONE);

        System.out.println("\n小数运算：");
        BigDecimal f0p1 = new BigDecimal("0.1");
        BigDecimal f0p2 = new BigDecimal("0.2");
        System.out.println(f0p1 + " + " + f0p2 + " = " + f0p1.add(f0p2));
        System.out.println(f0p1 + " - " + f0p2 + " = " + f0p1.subtract(f0p2));
        System.out.println(f0p1 + " * " + f0p2 + " = " + f0p1.multiply(f0p2));
        System.out.println(f0p1 + " / " + f0p2 + " = " + f0p1.divide(f0p2));
        System.out.println("sqrt(6.25) = " + new BigDecimal("6.25").sqrt(MathContext.UNLIMITED));
        System.out.println("sqrt(" + f0p1 + " * " + f0p2 + ") = " + f0p1.multiply(f0p2).sqrt(new MathContext(8, RoundingMode.HALF_UP)));

        System.out.println("\n大整数运算：");
        BigDecimal d641 = new BigDecimal("641");
        BigDecimal d6700417 = new BigDecimal("6700417");
        BigDecimal d4294967297 = new BigDecimal("4294967297");
        System.out.println(d641 + " * " + d6700417 + " = " + d641.multiply(d6700417));
        System.out.println(d4294967297 + " / " + d6700417 + " = " + d4294967297.divide(d6700417));
        System.out.println("2 ** 32 + 1 = " + (BigDecimal.valueOf(2).pow(32).add(BigDecimal.ONE)));
        System.out.println("2 ** 64 + 1 = " + (BigDecimal.valueOf(2).pow(64).add(BigDecimal.ONE)));

        System.out.println("\n舍入运算（四舍五入、向下取整、向上取整分别对应 HALF_UP, FLOOR, CEILING）：");
        System.out.println("1 / 7 = " + (BigDecimal.ONE.divide(BigDecimal.valueOf(7), RoundingMode.HALF_UP)));
        System.out.println("1 / 7 = " + (BigDecimal.ONE.divide(BigDecimal.valueOf(7), 1, RoundingMode.HALF_UP)));
        System.out.println("1 / 7 = " + (BigDecimal.ONE.divide(BigDecimal.valueOf(7), 2, RoundingMode.HALF_UP)));
        System.out.println("1 / 7 = " + (BigDecimal.ONE.divide(BigDecimal.valueOf(7), 5, RoundingMode.HALF_UP)));
        System.out.println("1 / 7 = " + (BigDecimal.ONE.divide(BigDecimal.valueOf(7), 10, RoundingMode.HALF_UP)));

        System.out.println("\n比较运算：");
        BigDecimal f1p1 = new BigDecimal("1.1");
        BigDecimal f1p10 = new BigDecimal("1.10");
        BigDecimal f2p1 = new BigDecimal("2.1");
        if (f1p1.compareTo(f2p1) < 0) {
            System.out.println("a.compareTo(b) < 0 代表 a < b");
        }
        if (f1p1.compareTo(f1p10) == 0) {
            System.out.println("a.compareTo(b) == 0 代表 a == b");
        }
        if (f2p1.compareTo(f1p1) > 0) {
            System.out.println("a.compareTo(b) > 0 代表 a > b");
        }

        System.out.println("\n潜在误区：");
        if (!f1p1.equals(f1p10)) {
            System.out.println("a == b 时 a.equals(b) 未必成立");
        }
        if (f1p1.compareTo(f1p10) == 0) {
            System.out.println("但 a.compareTo(b) == 0 一定成立");
        }
    }
}
